from aiogram_dialog import DialogManager
from fluentogram import TranslatorRunner
from sqlalchemy.ext.asyncio import AsyncSession

from src.application.proxy.service import ProxyService
from src.application.server.enums import ServerPrivacy, ServerType
from src.infrastructure.db.services.allowed_ips import get_allowed_ip_by_order
from src.infrastructure.db.services.categories import get_category, get_category_for_private
from src.infrastructure.db.services.orders.common import get_order
from src.infrastructure.db.services.orders.subscriptions import get_user_subscription_order
from src.infrastructure.db.services.proxy import get_available_proxies, get_proxy
from src.infrastructure.db.services.servers import get_server


async def proxy_getter(db_session: AsyncSession, dialog_manager: DialogManager, **kwargs):
    locale: TranslatorRunner = dialog_manager.middleware_data.get("locale")

    proxy_id: int = dialog_manager.dialog_data.get("proxy_id")
    proxy = await get_proxy(db_session, proxy_id, joined=True)
    user_id: int = dialog_manager.middleware_data["event_from_user"].id

    if dialog_manager.start_data and dialog_manager.start_data.get("order_id"):
        order_id: int = dialog_manager.start_data.get("order_id")
        order = await get_order(db_session, order_id, joined=True)
    else:
        order = await get_user_subscription_order(db_session, user_id)
        order_id = order.id
    allowed_ip = await get_allowed_ip_by_order(db_session, order.user.tg_id, order_id)  # TODO Вынести в юзкейс

    # TODO Вынести в отдельную функцию
    category = None
    country = None
    provider = None

    if locale.translators[0].locale == "ru":
        if order.country:
            country = order.country.name
        if order.category:
            category = order.category.name
        if order.provider:
            provider = order.provider.name
    else:
        if order.country:
            country = order.country.name_eng
        if order.category:
            category = order.category.name_eng
        if order.provider:
            provider = order.provider.name_eng

    site = order.site.name if order.site else None
    proxy_type = proxy.server.proxy_type
    proxy_privacy = proxy.server.proxy_privacy

    data = {
        "proxy_id": proxy.id,
        "ip_address": proxy.server.ip_address,
        "login": proxy.login,
        "password": proxy.password,
        "port_https": proxy.port_https,
        "proxy_type_translated": locale.get(proxy_type.value),
        "proxy_type": proxy_type.value,
        "proxy_privacy": proxy_privacy.value,
        "country": country,
        "category": category,
        "provider": provider,
        "site": site,
        "authorization_type": proxy.authorization_type,
        "authorization_type_translated": locale.get(proxy.authorization_type),
        "authorization_ip": allowed_ip.ip_address if allowed_ip else None,
    }

    if proxy_type == ServerType.mobile and proxy_privacy == ServerPrivacy.private:
        data.update(
            {
                "rotation_period": proxy.reload_period,
                "rotation_type": locale.get(proxy.reload_type),
            }
        )
    if proxy_type == ServerType.mobile and proxy.reload_type == "by_link":
        data.update(
            {
                "reload_modem_link": f"http://{proxy.server.ip_address}:{proxy.server.apache_port}/{proxy.reload_link}.php",
            }
        )

    return data


async def available_proxy_amount_getter(db_session: AsyncSession, dialog_manager: DialogManager, **kwargs):
    proxy_service: ProxyService = dialog_manager.middleware_data.get("proxy_service")

    proxy_type: str = dialog_manager.dialog_data.get("proxy_type")
    proxy_privacy: str = dialog_manager.dialog_data.get("proxy_privacy")

    country_id: int = dialog_manager.dialog_data.get("country_id")
    provider_id: int = dialog_manager.dialog_data.get("provider_id")
    category_id: int | None = dialog_manager.dialog_data.get("category_id")
    site_id: int = dialog_manager.dialog_data.get("site_id")
    user_telegram_id: int = dialog_manager.middleware_data.get("event_from_user").id

    print(category_id)
    print(dialog_manager.dialog_data)
    if category_id:
        category = await get_category(db_session, category_id)
    else:
        # Если прокси приватные, не указан id категории. Получаем категорию по стране сервера
        category = await get_category_for_private(db_session, country_id, provider_id)

    for_test = False
    limit = None
    # Получаем прокси для теста
    if dialog_manager.start_data and dialog_manager.start_data.get("for_test"):
        for_test = True
        limit = 1

    available_proxies = await proxy_service.get_available_proxies(
        proxy_type=getattr(ServerType, proxy_type),
        proxy_privacy=getattr(ServerPrivacy, proxy_privacy),
        country_id=country_id,
        provider_id=provider_id,
        category_id=category.id,
        site_id=site_id,
        limit=limit,
        tg_user_id=user_telegram_id,
    )

    dialog_manager.dialog_data["available_amount"] = available_proxies.total

    return {
        "available_amount": available_proxies.total,
        "for_test": for_test,
    }


async def available_proxies_for_replace_getter(db_session: AsyncSession, dialog_manager: DialogManager, **kwargs):
    order_id: int = dialog_manager.dialog_data.get("order_id")
    order = await get_order(db_session, order_id, joined=True)
    server = await get_server(db_session, order.proxies[0].server_id)
    available_proxies = await get_available_proxies(
        db_session,
        server.proxy_type.value,
        server.proxy_privacy.value,
        order.country_id,
        order.provider_id,
        order.category,
        order.site_id,
        order.user.tg_id,
    )

    return {"available_proxies": available_proxies}


async def order_proxies_getter(db_session: AsyncSession, dialog_manager: DialogManager, **kwargs):
    order_id: int = dialog_manager.dialog_data.get("order_id")
    if not order_id:
        order_id = dialog_manager.start_data.get("order_id")
    order = await get_order(db_session, order_id, joined=True)

    return {
        "proxies": order.proxies,
        "count": len(order.proxies),
    }
